package com.example.compose.utils

import android.os.Environment
import android.util.Log
import com.example.compose.App
import java.io.*
import java.text.DecimalFormat


object FileUtils {


    const val SIZETYPE_B = 1 //获取文件大小单位为B的double值

    const val SIZETYPE_KB = 2 //获取文件大小单位为KB的double值

    const val SIZETYPE_MB = 3 //获取文件大小单位为MB的double值

    const val SIZETYPE_GB = 4 //获取文件大小单位为GB的double值

    /**
     * 字符串写入文件
     */
    fun writeStringToFile(name: String,str: String,level:Int = 2):File?{
        makeFile(name,level)?.let { file ->
            try {
                val mRandomAccessFile = RandomAccessFile(file, "rwd")
                mRandomAccessFile.seek(file.length())
                mRandomAccessFile.write(str.toByteArray())
                mRandomAccessFile.close()
                LogUtil.i("写入成功file: $file")
            }catch (e:IOException){
                LogUtil.e("写入错误: $e")
            }
            return@writeStringToFile file
        }
        return null

    }

    /**
     * 读取文件String
     */
    fun readStringToFile(file: File?,level:Int = 2):String?{
        file?.let { path ->
            try {
                //如果设置插入了SD卡，并且应用程序具有访问SD卡的权限
//                if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
                val fis = FileInputStream(path)
                val br = BufferedReader(InputStreamReader(fis))
                val sb = StringBuilder("")
                var line: String? = null
                while (br.readLine().also { line = it } != null) {
                    sb.append(line)
                }
                br.close()
                return sb.toString()
//                }
            } catch (e: IOException) {
                e.printStackTrace()
                LogUtil.e("读取错误: $e")
            }
        }
        return null

    }

    /**
     * 生成文件
     * @author
     * @param fileName 文件名
     * @param level 文件目录等级 1:外部共享文件 *应用卸载之后不会删除 2：外部私有文件 3：内部存储文件
     * @param type 要返回的存储目录的类型。应该是其中之一
     * DIRECTORY_MUSIC, DIRECTORY_PODCASTS, DIRECTORY_RINGTONES,
     * DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS, DIRECTORY_PICTURES,
     * DIRECTORY_MOVIES, DIRECTORY_DOWNLOADS, DIRECTORY_DCIM or DIRECTORY_DOCUMENTS.
     * 不能为空
     */
    fun makeFile(fileName: String,level:Int = 2,type:String = Environment.DIRECTORY_DOCUMENTS): File? {
        var file: File? = null
        val filePath = when(level) {
            1 -> Environment.getExternalStoragePublicDirectory(type)
            3 -> App().getContext().filesDir
            else -> App().getContext().getExternalFilesDir(type)
        }
        filePath?.let {
            makeDirectory(it)
        }?: kotlin.run {
            LogUtil.e("生成文件夹为空")
            return null
        }
        try {
            file = File(filePath,fileName)
            if (!file.exists()) {
                file.parentFile?.let { makeDirectory(it) }
                file.createNewFile()
            }
        } catch (e: IOException) {
            LogUtil.e( "生成文件错误: $e")
        }
        return file
    }

    //生成文件夹
    private fun makeDirectory(file: File) {
        try {
            if (!file.exists()) {
                file.mkdir()
            }
        } catch (e: Exception) {
            LogUtil.e( "生成文件夹错误: $e")
        }
    }

    /**
     * 获取文件指定文件的指定单位的大小
     *
     * @param filePath 文件路径
     * @param sizeType 获取大小的类型1为B、2为KB、3为MB、4为GB
     * @return double值的大小
     */
    fun getFileOrFilesSize(filePath: String?, sizeType: Int): Double {
        val file = File(filePath)
        var blockSize: Long = 0
        try {
            blockSize = if (file.isDirectory) {
                getFileSizes(file)
            } else {
                getFileSize(file)
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            Log.e("获取文件大小", "获取失败!")
        }
        return FormetFileSize(blockSize, sizeType)
    }

    /**
     * 调用此方法自动计算指定文件或指定文件夹的大小
     *
     * @param filePath 文件路径
     * @return 计算好的带B、KB、MB、GB的字符串
     */
    fun getAutoFileOrFilesSize(filePath: String): String? {
        val file = File(filePath)
        var blockSize: Long = 0
        try {
            blockSize = if (file.isDirectory) {
                getFileSizes(file)
            } else {
                getFileSize(file)
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            Log.e("获取文件大小", "获取失败!")
        }
        return FormetFileSize(blockSize)
    }

    /**
     * 获取指定文件大小
     *
     * @param file
     * @return
     * @throws Exception
     */
    @Throws(java.lang.Exception::class)
    fun getFileSize(file: File): Long {
        var size: Long = 0
        if (file.exists()) {
            var fis: FileInputStream? = null
            fis = FileInputStream(file)
            size = fis.available().toLong()
        } else {
            file.createNewFile()
            Log.e("获取文件大小", "文件不存在!")
        }
        return size
    }

    /**
     * 获取指定文件夹
     *
     * @param f
     * @return
     * @throws Exception
     */
    @Throws(java.lang.Exception::class)
    private fun getFileSizes(f: File): Long {
        var size: Long = 0
        val flist = f.listFiles()
        for (i in flist.indices) {
            size = if (flist[i].isDirectory) {
                size + getFileSizes(flist[i])
            } else {
                size + getFileSize(flist[i])
            }
        }
        return size
    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    private fun FormetFileSize(fileS: Long): String {
        val df = DecimalFormat("#.00")
        var fileSizeString = ""
        val wrongSize = "0B"
        if (fileS == 0L) {
            return wrongSize
        }
        fileSizeString = if (fileS < 1024) {
            df.format(fileS.toDouble()) + "B"
        } else if (fileS < 1048576) {
            df.format(fileS.toDouble() / 1024) + "KB"
        } else if (fileS < 1073741824) {
            df.format(fileS.toDouble() / 1048576) + "MB"
        } else {
            df.format(fileS.toDouble() / 1073741824) + "GB"
        }
        return fileSizeString
    }

    /**
     * 转换文件大小,指定转换的类型
     *
     * @param fileS
     * @param sizeType
     * @return
     */
    private fun FormetFileSize(fileS: Long, sizeType: Int): Double {
        val df = DecimalFormat("#.00")
        var fileSizeLong = 0.0
        when (sizeType) {
            SIZETYPE_B -> fileSizeLong = java.lang.Double.valueOf(df.format(fileS.toDouble()))
            SIZETYPE_KB -> fileSizeLong =
                java.lang.Double.valueOf(df.format(fileS.toDouble() / 1024))
            SIZETYPE_MB -> fileSizeLong =
                java.lang.Double.valueOf(df.format(fileS.toDouble() / 1048576))
            SIZETYPE_GB -> fileSizeLong =
                java.lang.Double.valueOf(df.format(fileS.toDouble() / 1073741824))
            else -> {}
        }
        return fileSizeLong
    }
}
